package com.zxt.web.interceptor;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.core.NamedThreadLocal;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.UUID;

/**
 * @author zxt
 * 日志拦截器
 */
public class LoggingInterceptor implements HandlerInterceptor {
    private static final Logger LOGGER = LoggerFactory.getLogger(LoggingInterceptor.class);
    private static ThreadLocal<Long> starTimeThreadLocal = new NamedThreadLocal("ThreadLocal StartTime");

    public LoggingInterceptor() {
    }

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        starTimeThreadLocal.set(System.currentTimeMillis());
        String traceId = UUID.randomUUID().toString().replace("-", "").toUpperCase();
        MDC.put("traceId", traceId);
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
        String ip = httpServletRequest.getRemoteAddr();
        String uri = httpServletRequest.getRequestURI();
        String method = httpServletRequest.getMethod();
        String queryStr = httpServletRequest.getQueryString();
        if (StringUtils.isEmpty(queryStr)) {
            queryStr = "";
        }

        String protocol = httpServletRequest.getProtocol();
        int status = httpServletResponse.getStatus();
        long timeUsed = System.currentTimeMillis() - (Long) starTimeThreadLocal.get();
        LOGGER.info("{} \"{} {} {} {}\" {} {}ms", new Object[]{ip, method, uri, queryStr, protocol, status, timeUsed});
        starTimeThreadLocal.remove();
        MDC.remove("traceId");
    }
}
